package simulation;

import java.io.PrintStream;
import java.util.Vector;

public class FullStatistics extends Statistics {

	/* 2 tailed t distribution.
	 */
	static final double prob_exceed[ /* 6 */ ] = {.5, .2, .1, .05, .02, .01};

	Vector /* of TDistr */ tdistr;
	
	class TDistr {
		int df;         /* # degrees of freedom */
		double ucv[ /* 6 */ ];  /* upper critical value */

		public TDistr(int df, double ucv[]){
			this.df = df;
			this.ucv = ucv;
		}
	}

	/* t function.  df is the number of degrees of freedom (the number
	 * of measurements minus one.
	 */
	double tf(int df, double alpha, boolean two_tailed){
		/* First find the index in the probability of exceed table.
		 */
		if (!two_tailed) {
			alpha *= 2;
		}
		int i;
		for (i = 0; i < 6; i++) {
			double diff = prob_exceed[i] / alpha;
			if (0.99 < diff && diff < 1.01) {
				break;
			}
		}
		if (i == 6) {
			System.err.println("tf: don't support this prob of exceed");
			System.exit(1);
		}

		/* Now find the right row.
		 */
		for (int j = 0;; j++) {
			TDistr td = (TDistr) tdistr.elementAt(j);
			if (df == td.df) {
				return td.ucv[i];
			}
			if (td.df == 10000 || df < td.df) {
				j--;
				return td.ucv[i];
			}
		}
	}

	public FullStatistics(){
		
		super();
		
		/* Initialize the t distribution's constants.
		 */
		tdistr = new Vector();
		a(1, 1.000, 3.078, 6.314, 12.706, 31.821, 63.657);
		a(2, 0.816, 1.886, 2.920, 4.303, 6.965, 9.925);
		a(3, 0.765, 1.638, 2.353, 3.182, 4.541, 5.841);
		a(4, 0.741, 1.533, 2.132, 2.776, 3.747, 4.604);
		a(5, 0.727, 1.476, 2.015, 2.571, 3.365, 4.032);
		a(6, 0.718, 1.440, 1.943, 2.447, 3.143, 3.707);
		a(7, 0.711, 1.415, 1.895, 2.365, 2.998, 3.499);
		a(8, 0.706, 1.397, 1.860, 2.306, 2.896, 3.355);
		a(9, 0.703, 1.383, 1.833, 2.262, 2.821, 3.250);
		a(10, 0.700, 1.372, 1.812, 2.228, 2.764, 3.169);
		a(11, 0.697, 1.363, 1.796, 2.201, 2.718, 3.106);
		a(12, 0.695, 1.356, 1.782, 2.179, 2.681, 3.055);
		a(13, 0.694, 1.350, 1.771, 2.160, 2.650, 3.012);
		a(14, 0.692, 1.345, 1.761, 2.145, 2.624, 2.977);
		a(15, 0.691, 1.341, 1.753, 2.131, 2.602, 2.947);
		a(16, 0.690, 1.337, 1.746, 2.120, 2.583, 2.921);
		a(17, 0.689, 1.333, 1.740, 2.110, 2.567, 2.898);
		a(18, 0.688, 1.330, 1.734, 2.101, 2.552, 2.878);
		a(19, 0.688, 1.328, 1.729, 2.093, 2.539, 2.861);
		a(20, 0.687, 1.325, 1.725, 2.086, 2.528, 2.845);
		a(21, 0.686, 1.323, 1.721, 2.080, 2.518, 2.831);
		a(22, 0.686, 1.321, 1.717, 2.074, 2.508, 2.819);
		a(23, 0.685, 1.319, 1.714, 2.069, 2.500, 2.807);
		a(24, 0.685, 1.318, 1.711, 2.064, 2.492, 2.797);
		a(25, 0.684, 1.316, 1.708, 2.060, 2.485, 2.787);
		a(26, 0.684, 1.315, 1.706, 2.056, 2.479, 2.779);
		a(27, 0.684, 1.314, 1.703, 2.052, 2.473, 2.771);
		a(28, 0.683, 1.313, 1.701, 2.048, 2.467, 2.763);
		a(29, 0.683, 1.311, 1.699, 2.045, 2.462, 2.756);
		a(30, 0.683, 1.310, 1.697, 2.042, 2.457, 2.750);
		a(40, 0.681, 1.303, 1.684, 2.021, 2.423, 2.704);
		a(50, 0.679, 1.299, 1.676, 2.009, 2.403, 2.678);
		a(60, 0.679, 1.296, 1.671, 2.000, 2.390, 2.660);
		a(70, 0.678, 1.294, 1.667, 1.994, 2.381, 2.648);
		a(80, 0.678, 1.292, 1.664, 1.990, 2.374, 2.639);
		a(90, 0.677, 1.291, 1.662, 1.987, 2.368, 2.632);
		a(100, 0.677, 1.290, 1.660, 1.984, 2.364, 2.626);
		a(10000, 0.674, 1.282, 1.645, 1.960, 2.326, 2.576);
	}
	
	void a(int df, double u0, double u1, double u2, double u3, double u4, double u5){
		double[] ucv = new double[6];
		ucv[0] = u0;
		ucv[1] = u1;
		ucv[2] = u2;
		ucv[3] = u3;
		ucv[4] = u4;
		ucv[5] = u5;
		tdistr.add(new TDistr(df, ucv));
	}
	
	/* Calculate half the width of the confidence interval for the mean of a
	 * normal distribution with unknown variance using the t distribution.
	 * "confidence" here is typically .95 or .99.  Thus the 95% confidence
	 * interval is avg() +/- conf_interval(.95).
	 */
	public double conf_interval(double confidence){
		double t;

		t = tf(n - 1, 1 - confidence, true);
		return t * stdev();
	}
	
	public void dump(PrintStream out){
		double avg = avg()*10;
		double c95 = conf_interval(.95)*10;
		//double c99 = conf_interval(.99)*10;
		out.print("," + Math.round(avg) + "," + Math.round(avg - c95) + "," + Math.round(avg + c95));
	}
}
